﻿#ifndef _W_BASENODE_H_INCLUDE_
#define _W_BASENODE_H_INCLUDE_

#include <wx/wx.h>
#include <list>
#include <map>
#include "wxpolygonex.h"

class maindrawscene;
class WBaseNode;
class WNodeManager;

// 工作模式
enum WorkingMode
{
    MODE_WORKING = 0,     // 工作模式
    MODE_EIDTING,         // 编辑模式
    MODE_NULL
};

/// 结点类型
enum NodeType
{
    NODE_SWITCH = 0,      // 道岔
    NODE_SIGNAL,          // 信号灯
    NODE_MOUNT,           // 挂接点
    NODE_NULL
};

/// 挂载点方向
enum MountDirection
{
    DIRECTION_LEFT = 0,   // 左
    DIRECTION_RIGHT,      // 右
    DIRECTION_NULL
};

/// 结点的操作状态
enum NodeOperState
{
    CHOSEN = 0,        // 选中
    LOCKED,            // 锁闭
    NORMAL             // 正常
};

/// 结点的信号状态
enum NodeSignalState
{
    CLEAR = 0,         // 正常
    OCCUPY,            // 占用
    NOSIGNAL           // 没信号
};

/// 挂载点
struct tagMountPoint
{
    tagMountPoint()
        :node(NULL),level(0),direction(DIRECTION_NULL),angle(0.0f) {}
    tagMountPoint(wxString pname,wxRealPoint ppos,WBaseNode *pnode,int plevel,int dir)
        :name(pname),pos(ppos),node(pnode),level(plevel),direction(dir),angle(0.0f) {}

    int level;                // 等级
    wxRealPoint pos;          // 位置
    wxRealPoint screenpos;    // 屏幕显示位置
    WBaseNode* node;          // 关联结点
    int direction;            // 方向
    double angle;             // 角度
    wxString name;            // 挂接点的名称
};

struct tagSLRouteNode
{
    tagSLRouteNode()
        :node(NULL),MPointIndex(-1),sectPosition(-1) {}
    tagSLRouteNode(WBaseNode *pnode,const int index,wxString sName="",int sPosition=-1)
        : node(pnode),MPointIndex(index),sectName(sName),sectPosition(sPosition) {}

    WBaseNode* node;
    int MPointIndex;
    wxString sectName;
    int sectPosition;
};

class WBaseNode
{
public:
    WBaseNode();
    WBaseNode(const wxString& pname);
    virtual ~WBaseNode();

    /// 得到结点管理器
    inline WNodeManager* getNodeManager(void) { return mNodeManager; }
    /// 设置名称
    inline void setName(const wxString& name) { mName = name; }
    /// 得到名称
    inline const wxString& getName(void) { return mName; }
    /// 设置设备ID
    inline void setDeviceID(int id) { mDeviceID = id; }
    /// 得到设备ID
    inline int getDeviceID(void) { return mDeviceID; }
    /// 设置结点类型
    inline void setNodeType(int ptype) { mNodeType = (NodeType)ptype; }
    /// 得到结点类型
    inline int getNodeType(void) { return (int)mNodeType; }
    /// 设置结点的操作状态
    inline void setOperState(int state) { mNodeOperState = (NodeOperState)state; }
    /// 得到结点的操作状态
    inline int getOperState(void) { return (int)mNodeOperState; }
    /// 设置结点的信号状态
    inline void setSignalState(int state) { mNodeSignalState = (NodeSignalState)state; }
    /// 得到结点的信号状态
    inline int getSignalState(void) { return (int)mNodeSignalState; }
    /// 设置结点的工作模式
    inline void setWorkingMode(WorkingMode mode) { mWorkingMode = mode; }
    /// 得到结点的工作模式
    inline WorkingMode getWorkingMode(void) { return mWorkingMode; }
    /// 设置包围盒
    inline void setBoundingRect(const wxPolygonEx& rect) { mboundingRect = rect; }
    /// 得到包围盒
    inline const wxPolygonEx& getBoundingRect(void) { return mboundingRect; }
    /// 设置挂接点的显示位置
    void setPosition(wxRealPoint pos);
    /// 得到挂接点的显示位置
    inline wxRealPoint getPosition(void) { return mCenterPosition; }
    /// 得到计算后的屏幕显示位置
    inline wxRealPoint getScreenPosition(void) { return mScreenCenterPosition; }
    /// 根据状态得到颜色
    virtual wxColour getColourByState(void);
    /// 根据状态得到文字颜色
    wxColour getTextColourByState(void);
    /// 得到当前结点所有挂结点信息
    const std::map<wxString,tagMountPoint> getAllMountPoints(void) { return mMountPoints; }

    /// 设置当前结点的父结点
    inline void setParentNode(WBaseNode *node) { mParentNode = node; }
    /// 得到当前结点的父结点
    inline WBaseNode* getParentNode(void) { return mParentNode; }

    /// 添加一个挂载点
    bool addMountPoint(wxString name,const tagMountPoint& point);
    /// 检测指定名称的挂载点是否存在
    bool isExistMountPoint(wxString name);
    /// 得到指定名称的挂载点
    tagMountPoint* getMountPointByName(wxString name);
    /// 删除指定名称的挂载点
    void deleteMountPoint(wxString name);
    /// 设置指定名称挂接点的角度
    void setMountPointAngle(wxString name,double angle);
    /// 删除所有的挂载点
    inline void deleteAllMountPoints(void) { mMountPoints.clear(); }
    /// 得到指定方向上的所有挂载点
    wxVector<tagMountPoint> getMountPointByDir(int dir);
    /// 检查指定结点是否在当前结点的挂载点内
    bool isExistMountNode(WBaseNode* node,int dir,tagMountPoint* point);

    /// 设置结点管理器
    virtual void setNodeManager(WNodeManager *pNodeManager) { mNodeManager = pNodeManager; }
    /// 工作区域改变
    virtual void changeWorkingRect(wxRect workingrect);
    /// 更新
    virtual void update(void) {}
    /// 绘制
    virtual void draw(maindrawscene *painter) {}
    /// 处理鼠标事件
    virtual bool OnMMouseEvent(wxMouseEvent& event) { return false; }
    /// 重置结点状态
    virtual void reset(void);

protected:
    wxRealPoint mCenterPosition;                     /**< 显示位置，屏幕的百分比，以便于拉伸 */
    wxRealPoint mScreenCenterPosition;               /**< 结算后的屏幕中心点 */

private:
    WNodeManager *mNodeManager;                      /**< 结点管理器 */
    WorkingMode mWorkingMode;                        /**< 结点的工作模式 */
    wxString mName;                                  /**< 结点名称 */
    int mDeviceID;                                   /**< 结点的设备ID */
    NodeType mNodeType;                              /**< 结点类型 */
    NodeOperState mNodeOperState;                    /**< 结点的操作状态 */
    NodeSignalState mNodeSignalState;                /**< 结点的信号状态 */
    wxPolygonEx mboundingRect;                       /**< 包围盒 */
    WBaseNode* mParentNode;                          /**< 当前结点的父结点 */
    std::map<wxString,tagMountPoint> mMountPoints;   /**< 当前结点的挂载点 */
};

#endif // BASEOBJECT_H
